﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	SystemControl.cs
//  Developer:	Solomatov Igor
//  Created:	03.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Collections;
using System.ComponentModel;
using System.Text;
using System.Threading;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Smart.Common.Entities;

namespace Smart.Common.WebControls
{
	[Localizable(false), ToolboxData("<{0}:SystemControl runat=server></{0}:SystemControl>")]
	public class SystemControl : WebControl
	{
		public SystemControl()
			: base(HtmlTextWriterTag.Div)
		{
			Style[HtmlTextWriterStyle.Margin] = "4px 4px 4px 4px";
		}

		protected Label lVersion;
		protected Button bClearLists;
		protected Button bClearMain;
		protected Button bGetCache;
		protected Button bSchemaUp;
		protected Button bSchemaDown;
		protected Button bCheckErrors;
		protected Button bCorrectErrors;
		protected LiteralControl lCache;
		protected Label lResult;

		public virtual void DefineCtrls()
		{
			if (!DesignMode && Controls.Count <= 0)
			{
				lVersion = new Label { ID = "lv" };

				Controls.Add(lVersion);
				Controls.Add(new LiteralControl("<br/><br/>"));

				Controls.Add(new LiteralControl("<b>Actions:</b><br/>"));
				bClearLists = new Button
								{
									ID = "clists",
									Text = "Purge Lists cache",
									Width = Unit.Pixel(150),
									ToolTip = "Disabled"
								};

				Controls.Add(bClearLists);
				Controls.Add(new LiteralControl("<br/>"));

				bClearMain = new Button { ID = "cmain", Text = "Purge Main cache", Width = Unit.Pixel(150) };

				Controls.Add(bClearMain);
				Controls.Add(new LiteralControl("<br/>"));

				bGetCache = new Button { ID = "gc", Text = "Get cache", Width = Unit.Pixel(150) };

				Controls.Add(bGetCache);
				Controls.Add(new LiteralControl("<br/><br/>"));

				bCheckErrors = new Button { ID = "bche", Text = "Check Errors", Width = Unit.Pixel(150) };

				Controls.Add(bCheckErrors);
				Controls.Add(new LiteralControl("<br/>"));

				bCorrectErrors = new Button { ID = "bcoe", Text = "Correct Errors", Width = Unit.Pixel(150) };

				Controls.Add(bCorrectErrors);
				Controls.Add(new LiteralControl("<br/><br/>"));

				bSchemaUp = new Button { ID = "bsu", Text = "Schema Up", Width = Unit.Pixel(150) };

				Controls.Add(bSchemaUp);
				Controls.Add(new LiteralControl("<br/>"));

				bSchemaDown = new Button { ID = "bsd", Text = "Schema Down", Width = Unit.Pixel(150) };

				Controls.Add(bSchemaDown);

				SPServices.EventManager.FireEvent(Const.EventNames.System.DefineControls, Page, Controls);

				Controls.Add(new LiteralControl("<br/><br/><br/>"));

				Controls.Add(new LiteralControl("<b>Cache info:</b><br/>"));
				lCache = new LiteralControl { ID = "lc", Text = string.Empty };

				Controls.Add(lCache);
				Controls.Add(new LiteralControl("<br/><br/>"));

				Controls.Add(new LiteralControl("<b>Action results:</b><br/>"));
				lResult = new Label { ID = "lr", Text = string.Empty };

				Controls.Add(lResult);

				bClearLists.Click += BClearListsClick;
				bClearMain.Click += BClearMainClick;
				bGetCache.Click += BGetCacheClick;
				bCheckErrors.Click += BCheckErrorsClick;
				bCorrectErrors.Click += BCorrectErrorsClick;
				bSchemaUp.Click += bSchemaUp_Click;
				bSchemaDown.Click += bSchemaDown_Click;

				lVersion.Text =
					string.Format("<b>{0} {1}, Schema={2}, ProcessID={3}, ThreadID={4}</b>",
								  H.Product, H.Version, GetSchemaVersion(),
								  System.Diagnostics.Process.GetCurrentProcess().Id,
								  Thread.CurrentThread.ManagedThreadId);

				UpdateCtrls(false);
			}
		}

		private string GetSchemaVersion()
		{
			var web = SPH.GetWeb();

			string value = null;

			if (web.Properties.ContainsKey(SN.SchemaVersionKey))
				value = web.Properties[SN.SchemaVersionKey];

			return value ?? "";
		}

		private void bSchemaUp_Click(object sender, EventArgs e)
		{
			SPH.RunElevated(
				delegate
				{
					var web = SPH.GetWeb();

					string value = null;

					if (web.Properties.ContainsKey(SN.SchemaVersionKey))
						value = web.Properties[SN.SchemaVersionKey];

					var created = false;

					//if (string.IsNullOrEmpty(Value))
					//{
					//    SPList List = SPH.GetList(Web, SN.WeeksPlan);
					//    if (List != null)
					//    {
					//        Web.AllowUnsafeUpdates = true;
					//        for (int I = 1; I <= COCR.WeeksSz; I++)
					//        {
					//            string Field = SN.WeeField + I.ToString("00");
					//            List.Fields.Add(Field, SPFieldType.Number, false);
					//        }
					//        try
					//        {
					//            List.Update();
					//            Created = true;
					//        }
					//        catch (Exception x)
					//        {
					//            H.LX("bSchemaUp_Click.CF", x);
					//        }
					//        Web.AllowUnsafeUpdates = false;
					//        Value = SN.SchemaVersion_WeeksPlan;
					//        if (Created)
					//            lResult.Text += "Schema successfully updated! User: " + SPH.CurrentUser().LoginName +
					//                            ", Schema Version: " + Value + "<br/>";
					//    }
					//}
					//else if (Value.In(SN.SchemaVersion_WeeksPlan))
					//{
					//    SPList List = SPH.GetList(Web, SN.ConstructionObjects);
					//    if (List != null)
					//    {
					//        Web.AllowUnsafeUpdates = true;
					//        for (int I = 1; I <= 6; I++)
					//        {
					//            string FieldName1 = SN.OrderOPlanDateFieldTmpl + I.ToString();
					//            List.Fields.Add(FieldName1, SPFieldType.DateTime, false);
					//            string FieldName2 = SN.OrderCPlanDateFieldTmpl + I.ToString();
					//            List.Fields.Add(FieldName2, SPFieldType.DateTime, false);
					//        }
					//        try
					//        {
					//            List.Update();
					//            Created = true;
					//        }
					//        catch (Exception x)
					//        {
					//            H.LX("bSchemaUp_Click.CF", x);
					//        }
					//        Web.AllowUnsafeUpdates = false;
					//        Value = SN.SchemaVersion_OrderPlan;
					//        if (Created)
					//            lResult.Text += "Schema successfully updated! User: " + SPH.CurrentUser().LoginName +
					//                            ", Schema Version: " + Value + "<br/>";
					//    }
					//}

					if (created)
					{
						using (new UnsafeUpdate(web))
						{
							web.Properties[SN.SchemaVersionKey] = value;

							try
							{
								web.Properties.Update();
							}
							catch (Exception x)
							{
								H.LX("bSchemaUp_Click.CF_WPU", x);
							}
						}
					}
					else
					{
						lResult.Text += "Schema was not changed!<br/>";
					}
				});
		}

		private void bSchemaDown_Click(object sender, EventArgs e)
		{
			SPH.RunElevated(
				delegate
				{
					var web = SPH.GetWeb();

					string value = null;

					if (web.Properties.ContainsKey(SN.SchemaVersionKey))
						value = web.Properties[SN.SchemaVersionKey];

					var deleted = false;

					//if (value.In(SN.SchemaVersion_OrderPlan))
					//{
					//    // drop existing columns
					//    SPList List = SPH.GetList(web, SN.ConstructionObjects);
					//    if (List != null)
					//    {
					//        web.AllowUnsafeUpdates = true;
					//        List<SPField> Fields = new List<SPField>();
					//        foreach (SPField Field in List.Fields)
					//        {
					//            if (Field.InternalName.StartsWith(SN.OrderOPlanDateFieldTmpl) || Field.InternalName.StartsWith(SN.OrderCPlanDateFieldTmpl))
					//            {
					//                Fields.Add(Field);
					//            }
					//        }
					//        foreach (SPField Field in Fields)
					//        {
					//            Field.Delete();
					//        }
					//        try { List.Update(); deleted = true; }
					//        catch (Exception x) { H.LX("bSchemaDown_Click.DF", x); }
					//        web.AllowUnsafeUpdates = false;
					//        value = SN.SchemaVersion_WeeksPlan;
					//        if (deleted)
					//            lResult.Text += "Schema successfully downgraded! User: " + SPH.CurrentUser().LoginName + ", Schema Version: " + value + "<br/>";
					//    }
					//}
					//else if (value.In(SN.SchemaVersion_WeeksPlan))
					//{
					//    // drop existing columns
					//    SPList List = SPH.GetList(web, SN.WeeksPlan);
					//    if (List != null)
					//    {
					//        web.AllowUnsafeUpdates = true;
					//        List<SPField> Fields = new List<SPField>();
					//        foreach (SPField Field in List.Fields)
					//        {
					//            if (Field.InternalName.StartsWith(SN.WeeField))
					//            {
					//                Fields.Add(Field);
					//            }
					//        }
					//        foreach (SPField Field in Fields)
					//        {
					//            Field.Delete();
					//        }
					//        try { List.Update(); deleted = true; }
					//        catch (Exception x) { H.LX("bSchemaDown_Click.DF", x); }
					//        web.AllowUnsafeUpdates = false;
					//        value = string.Empty;
					//        if (deleted)
					//            lResult.Text += "Schema successfully downgraded! User: " + SPH.CurrentUser().LoginName + ", Schema Version: " + value + "<br/>";
					//    }
					//}

					if (deleted)
					{
						using (new UnsafeUpdate(web))
						{
							web.Properties[SN.SchemaVersionKey] = value;

							try
							{
								web.Properties.Update();
							}
							catch (Exception x)
							{
								H.LX("bSchemaDown_Click.DF_WPU", x);
							}
						}
					}
					else
					{
						lResult.Text += "Schema was not changed!<br/>";
					}
				});
		}

		private void BCheckErrorsClick(object sender, EventArgs e)
		{
			SPServices.EventManager.FireEvent(Const.EventNames.System.CheckErrors, Page, Controls);
		}

		private void BCorrectErrorsClick(object sender, EventArgs e)
		{
			SPServices.EventManager.FireEvent(Const.EventNames.System.CorrectErrors, Page, Controls);

			/*
			var succeeded = false;
			var messages = "";

			var returnUrl = Page.Request.RawUrl;

			try
			{
				using (SPLongOperation LO = new SPLongOperation(Page))
				{
					LO.SetLeadingWithSpan("Checking and Correcting OD");
					LO.SetTrailingWithSpan("Please wait while checking and correcting OD, it can take up to 30 minutes to complete!");

					LO.Begin();

					SPH.RunElevated(delegate
										{
											//List<OD.CheckErrorInfo> Errors;
											//succeeded = OD.CheckData(true, out Errors, new Action<string, string, int, int>(delegate(string StepName, string Action, int Current, int Count)
											//    {
											//        LO.SetDynamicTrailing(string.Format("{0}: {1} ({2} of {3})", StepName, Action, Current, Count));
											//    }));
											//if (Errors != null)
											//    messages = Errors.Select(Error => Error.Message + "<br/>").CastToString("");
										});

					var qIdx = returnUrl.LastIndexOf('?');

					if (qIdx >= 0)
						returnUrl = returnUrl.Substring(0, qIdx);

					returnUrl += "?Text=";

					returnUrl += H.EncodeUri((succeeded ? "Correct OD succeeded!!!<br/>" : "Correct OD failed!!!<br/>") + messages);

					LO.End(returnUrl);
				}
			}
			catch (ThreadAbortException)
			{
				// Thrown when redirected
			}
			catch (Exception x)
			{
				SPUtility.TransferToErrorPage(x.ToString());
			}
			 */
		}

		private void BGetCacheClick(object sender, EventArgs e)
		{
			lCache.Text =
				string.Format(
					"<table cellspacing=0 cellpadding=2 border=1 style=\"border-collapse:collapse;\">" +
					"<tr class=ms-vb><td colspan=3>main (main)</td></tr>{0}" +
					"<tr class=ms-vb><td colspan=3>main (request)</td></tr>{1}</table>",
					GetMainCacheInfo(), GetRequestStoreInfo());
		}

		private string GetMainCacheInfo()
		{
			var res = new StringBuilder();

			var count = 0;

			foreach (DictionaryEntry de in SPServices.Cache.MainCache)
			{
				count++;

				res.AppendFormat("<tr class=ms-vb><td>{0}</td><td>{1}</td><td>{2}</td></tr>", count,
								 (de.Key.SToStr(null) ?? "null").EncodeHtml(), (de.Value.SToStr(null) ?? "null").EncodeHtml());
			}

			res.AppendFormat("<tr class=ms-vb><td>&nbsp;</td><td style=\"font-weight:bold;\">Total</td><td>{0}</td></tr>", count);

			return res.ToString();
		}

		private string GetRequestStoreInfo()
		{
			var res = new StringBuilder();

			var count = 0;

			foreach (DictionaryEntry de in SPServices.Cache.RequestStore)
			{
				count++;

				res.AppendFormat("<tr class=ms-vb><td>{0}</td><td>{1}</td><td>{2}</td></tr>", count,
								 de.Key.SToStr("null").EncodeHtml(), de.Value.SToStr("null").EncodeHtml());
			}

			res.AppendFormat("<tr class=ms-vb><td>&nbsp;</td><td style=\"font-weight:bold;\">Total</td><td>{0}</td></tr>", count);

			return res.ToString();
		}

		private void BClearMainClick(object sender, EventArgs e)
		{
			SPServices.Cache.Clear();

			lResult.Text += "Main cache was cleared!<br/>";
		}

		private void BClearListsClick(object sender, EventArgs e)
		{
			ListServiceCache.Clear();

			lResult.Text += "Lists cache in main cache cleared!<br/>";
		}

		public virtual void UpdateCtrls(bool updateValue)
		{
			if (Controls.Count <= 0) return;

			SPServices.EventManager.FireEvent(Const.EventNames.System.UpdateControls, Page, Controls, updateValue);

			// do nothing
			//...

			// Update values
			if (!updateValue) return;

			SPH.RunElevated(
				delegate
				{
					//SPList NT = SPH.GetList(SN.NotificationTemplatesKey.Localized());
					//SPListItem Item = SPH.GetFilteredItem(NT, SPH.GetCAMLFilterEnclosure(SPH.GetCAMLFilterEq(NT, SN.TitleField, "ObjectNotificationTemplate")));
					//if (Item != null)
					//{
					//    tbObjectTemplate.Text = SPH.GetItemValueStr(Item, SN.TemplateYesField);
					//}
				});
		}

		protected bool CheckSecurity()
		{
			return SPH.GetWeb().UserIsSiteAdmin;
		}

		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);

			DefineCtrls();

			if (!CheckSecurity())
			{
				SPUtility.HandleAccessDenied(new SPException("Пользователь не имеет прав доступа к данной информации!"));
			}
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			if (Page.IsPostBack) return;

			var text = Page.Request.QueryString["Text"];

			if (!string.IsNullOrEmpty(text))
				lResult.Text += text;
		}

		protected override void OnPreRender(EventArgs e)
		{
			if (!Page.IsPostBack)
				UpdateCtrls(true);
		}
	}
}